/**
*******************************************************
*@file  spi.c
*@brief spi.c
*@author 花满楼
*@date     2020-7-1 
*@version  V1
*@attention none
*******************************************************
*/
#include "spi.h"

SPI_HandleTypeDef SPI4_Handler;  ///<SPI4句柄
SPI_HandleTypeDef SPI5_Handler;  ///<SPI5句柄
SPI_HandleTypeDef SPI1_Handler;  ///<SPI1句柄


/**
*******************************************************
*@brief SPI初始化，SPI4用于25AA256的EEP;SPI1用于ADS1260的电流采样,SPI5用于电芯电压和温度采样
*@param   none
*@return  none
*@note    SPI4、SPI5挂在APB2是84MHz，
*******************************************************
*/
void SPI_Init()
{
	/*****************用于25AA256，EEP*****************/
    SPI4_Handler.Instance = SPI4;                       //SP4       
    SPI4_Handler.Init.Mode = SPI_MODE_MASTER;           //设置SPI工作模式，设置为主模式
    SPI4_Handler.Init.Direction = SPI_DIRECTION_2LINES; //设置SPI单向或者双向的数据模式:SPI设置为双线模式
    SPI4_Handler.Init.DataSize = SPI_DATASIZE_8BIT;     //设置SPI的数据大小:SPI发送接收8位帧结构
    SPI4_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;   //串行同步时钟的空闲状态为低电平
    SPI4_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;       //串行同步时钟的第一个跳变沿（上升或下降）数据被采样
    SPI4_Handler.Init.NSS = SPI_NSS_SOFT;               //NSS信号由硬件（NSS管脚）还是软件（使用SSI位）管理:内部NSS信号有SSI位控制
    SPI4_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; //定义波特率预分频的值:波特率预分频值为16 84/16=5.25M
    SPI4_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;      //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
    SPI4_Handler.Init.TIMode = SPI_TIMODE_DISABLE;      //关闭TI模式
    SPI4_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; //关闭硬件CRC校验
    SPI4_Handler.Init.CRCPolynomial = 7;                //CRC值计算的多项式
    HAL_SPI_Init(&SPI4_Handler);    //初始化
    __HAL_SPI_ENABLE(&SPI4_Handler);                    //使能SPI4
    SPI4_ReadWriteByte(0Xff);                           //启动传输
	/*****************用于电芯电压和温度采样*****************/
    SPI5_Handler.Instance = SPI5;                       //SP5  
    SPI5_Handler.Init.Mode = SPI_MODE_MASTER;           //设置SPI工作模式，设置为主模式
    SPI5_Handler.Init.Direction = SPI_DIRECTION_2LINES; //设置SPI单向或者双向的数据模式:SPI设置为双线模式
    SPI5_Handler.Init.DataSize = SPI_DATASIZE_8BIT;     //设置SPI的数据大小:SPI发送接收8位帧结构
    SPI5_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;     //串行同步时钟的空闲状态为低电平
    SPI5_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;       //串行同步时钟的第一个跳变沿（上升或下降）数据被采样
    SPI5_Handler.Init.NSS = SPI_NSS_SOFT;               //NSS信号由硬件（NSS管脚）还是软件（使用SSI位）管理:内部NSS信号有SSI位控制
    SPI5_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; //定义波特率预分频的值:波特率预分频值为16 84/16=5.25M
    SPI5_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;      //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
    SPI5_Handler.Init.TIMode = SPI_TIMODE_DISABLE;      //关闭TI模式
    SPI5_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; //关闭硬件CRC校验
    SPI5_Handler.Init.CRCPolynomial = 7;//0x87;             //CRC值计算的多项式
    HAL_SPI_Init(&SPI5_Handler);    //初始化
    __HAL_SPI_ENABLE(&SPI5_Handler);                    //使能SPI5
    SPI5_ReadWriteByte(0xff);                           //启动传输
	/*****************用于ADS1260 电流采样信号*****************/	
    SPI1_Handler.Instance = SPI1;                       //SP1
    SPI1_Handler.Init.Mode = SPI_MODE_MASTER;           //设置SPI工作模式，设置为主模式
    SPI1_Handler.Init.Direction = SPI_DIRECTION_2LINES; //设置SPI单向或者双向的数据模式:SPI设置为双线模式
    SPI1_Handler.Init.DataSize = SPI_DATASIZE_8BIT;     //设置SPI的数据大小:SPI发送接收8位帧结构
    SPI1_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;   //串行同步时钟的空闲状态为低电平
    SPI1_Handler.Init.CLKPhase = SPI_PHASE_2EDGE;       //串行同步时钟的第二个跳变沿（上升或下降）数据被采样
    SPI1_Handler.Init.NSS = SPI_NSS_SOFT;               //NSS信号由硬件（NSS管脚）还是软件（使用SSI位）管理:内部NSS信号有SSI位控制
    SPI1_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; //定义波特率预分频的值:波特率预分频值为64
    SPI1_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;      //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
    SPI1_Handler.Init.TIMode = SPI_TIMODE_DISABLE;      //关闭TI模式
    SPI1_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; //关闭硬件CRC校验
    SPI1_Handler.Init.CRCPolynomial = 7;                //CRC值计算的多项式
    HAL_SPI_Init(&SPI1_Handler);    //初始化
    __HAL_SPI_ENABLE(&SPI1_Handler);                    //使能SPI1
    SPI1_ReadWriteByte(0Xff);                           //启动传输
    AA256_CS = 1;        //EEPROM
}


/**
*******************************************************
*@brief SPI4底层驱动，时钟使能，引脚配置
*@param   hspi:SPI句柄
*@return  none
*@note    此函数会被HAL_SPI_Init()调用
*******************************************************
*/
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_GPIOE_CLK_ENABLE();       //使能GPIOE时钟
    __HAL_RCC_GPIOF_CLK_ENABLE();       //使能GPIOF时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();       //使能GPIOA时钟
    __HAL_RCC_SPI4_CLK_ENABLE();        //使能SPI4时钟
    __HAL_RCC_SPI5_CLK_ENABLE();        //使能SPI5时钟
    __HAL_RCC_SPI1_CLK_ENABLE();        //使能SPI1时钟
	
    GPIO_Initure.Pin = GPIO_PIN_11;		//SPI4 --->CS
    GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;    //通用推挽输出
    GPIO_Initure.Pull = GPIO_PULLUP;            //上拉
    GPIO_Initure.Speed = GPIO_SPEED_FAST;       //快速
    HAL_GPIO_Init(GPIOE, &GPIO_Initure);
    GPIO_Initure.Pin = GPIO_PIN_6;		//SPI5--->CS
    HAL_GPIO_Init(GPIOF, &GPIO_Initure);
    GPIO_Initure.Pin = GPIO_PIN_4;		//SPI1--->CS
    HAL_GPIO_Init(GPIOA, &GPIO_Initure);
	/**SPI4 GPIO Configuration   
    PE12     ------> SPI4_SCK
    PE13     ------> SPI4_MOSI
    PE14     ------> SPI4_MISO
    */
    GPIO_Initure.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14;
    GPIO_Initure.Mode = GPIO_MODE_AF_PP;            //复用推挽输出
    GPIO_Initure.Pull = GPIO_PULLUP;                //上拉
    GPIO_Initure.Speed = GPIO_SPEED_FAST;           //快速
    GPIO_Initure.Alternate = GPIO_AF5_SPI4;         //复用为SPI4
    HAL_GPIO_Init(GPIOE, &GPIO_Initure);
	/**SPI5 GPIO Configuration   
    PF7     ------> SPI5_SCK
    PF8     ------> SPI5_MISO
    PF9     ------> SPI5_MOSI
    */
    GPIO_Initure.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9;
    GPIO_Initure.Mode = GPIO_MODE_AF_PP;            //复用推挽输出
    GPIO_Initure.Pull = GPIO_PULLUP;                //上拉
    GPIO_Initure.Speed = GPIO_SPEED_FAST;           //快速
    GPIO_Initure.Alternate = GPIO_AF5_SPI5;         //复用为SPI5
    HAL_GPIO_Init(GPIOF, &GPIO_Initure);
    /**SPI1 GPIO Configuration   
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    */
    GPIO_Initure.Pin = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_Initure.Mode = GPIO_MODE_AF_PP;            //复用推挽输出
    GPIO_Initure.Pull = GPIO_PULLUP;                //上拉
    GPIO_Initure.Speed = GPIO_SPEED_FAST;           //快速
    GPIO_Initure.Alternate = GPIO_AF5_SPI1;         //复用为SPI1
    HAL_GPIO_Init(GPIOA, &GPIO_Initure);
}

/**
*******************************************************
*@brief SPI速度设置函数
*@param   SPI_BaudRate_Prescaler:SPI_BAUDRATEPRESCALER_2~SPI_BAUDRATEPRESCALER_2 256
*@return  none
*@note    SPI速度=fAPB1/分频系数
          fAPB1时钟一般为45Mhz：
*******************************************************
*/
void SPI4_SetSpeed(u8 SPI_BaudRatePrescaler)
{
    assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));       //判断有效性
    __HAL_SPI_DISABLE(&SPI4_Handler);            //关闭SPI
    SPI4_Handler.Instance->CR1 &= 0XFFC7;        //位3-5清零，用来设置波特率
    SPI4_Handler.Instance->CR1 |= SPI_BaudRatePrescaler; //设置SPI速度
    __HAL_SPI_ENABLE(&SPI4_Handler);             //使能SPI
}
/**
*******************************************************
*@brief SPI速度设置函数
*@param   SPI_BaudRate_Prescaler:SPI_BAUDRATEPRESCALER_2~SPI_BAUDRATEPRESCALER_2 256
*@return  none
*@note    SPI速度=fAPB1/分频系数
          fAPB1时钟一般为45Mhz：
*******************************************************
*/
void SPI5_SetSpeed(u8 SPI_BaudRatePrescaler)
{
    assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));       //判断有效性
    __HAL_SPI_DISABLE(&SPI5_Handler);            //关闭SPI
    SPI5_Handler.Instance->CR1 &= 0XFFC7;        //位3-5清零，用来设置波特率
    SPI5_Handler.Instance->CR1 |= SPI_BaudRatePrescaler; //设置SPI速度
    __HAL_SPI_ENABLE(&SPI5_Handler);             //使能SPI
}
/**
*******************************************************
*@brief SPI速度设置函数
*@param   SPI_BaudRate_Prescaler:SPI_BAUDRATEPRESCALER_2~SPI_BAUDRATEPRESCALER_2 256
*@return  none
*@note    SPI速度=fAPB1/分频系数
          fAPB1时钟一般为45Mhz：
*******************************************************
*/
void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler)
{
    assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));       //判断有效性
    __HAL_SPI_DISABLE(&SPI1_Handler);            //关闭SPI
    SPI1_Handler.Instance->CR1 &= 0XFFC7;        //位3-5清零，用来设置波特率
    SPI1_Handler.Instance->CR1 |= SPI_BaudRatePrescaler; //设置SPI速度
    __HAL_SPI_ENABLE(&SPI1_Handler);             //使能SPI
}

/**
*******************************************************
*@brief SPI1 读写一个字节
*@param   TxData:要写入的字节
*@return  读取到的字节
*@note    none
*******************************************************
*/
u8 SPI1_ReadWriteByte(u8 TxData)
{
    u8 Rxdata;
    HAL_SPI_TransmitReceive(&SPI1_Handler, &TxData, &Rxdata, 1, 10);
    return Rxdata;                      //返回收到的数据
}

/**
*******************************************************
*@brief SPI4 读写一个字节
*@param   TxData:要写入的字节
*@return  读取到的字节
*@note    none
*******************************************************
*/
u8 SPI4_ReadWriteByte(u8 TxData)
{
    u8 Rxdata;
    HAL_SPI_TransmitReceive(&SPI4_Handler, &TxData, &Rxdata, 1, 10);
    return Rxdata;                      //返回收到的数据
}


/**
*******************************************************
*@brief SPI5 读写一个字节
*@param   TxData:要写入的字节
*@return  读取到的字节
*@note    none
*******************************************************
*/
u8 SPI5_ReadWriteByte(u8 TxData)
{
    u8 Rxdata;
    HAL_SPI_TransmitReceive(&SPI5_Handler, &TxData, &Rxdata, 1, 10);
    return Rxdata;                      //返回收到的数据
}

